package com.yyh.common.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Json转换工具类
 * @author xuan
 * @date 2021/11/2
 */
public class JsonUtils {

    /**
     * 将对象转换为json
     * @param object
     * @return
     */
    public static String toJson(Object object) {
        ObjectMapper objectMapper = new ObjectMapper();
        String json = null;
        try {
            json = objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e.getMessage(), e.getCause());
        }

        return json;
    }

    /**
     * 将json转为 java对象
     * @param str 待解析的字符串
     * @return
     */
    public static Object parseJson(String str) {
        JsonNode root = null;
        try {
            root = new ObjectMapper().readTree(str);
        } catch (JsonProcessingException e) {
            // 编译异常 转换为运行异常
            throw new RuntimeException(e.getMessage(), e.getCause());
        }
        return traverse(root);
    }

    /**
     * 解析对象时使用的递归
     * @param root
     * @return
     */
    private static Object traverse(JsonNode root){

        if(root.isObject()){
            // 当前node为json对象
            HashMap<String, Object> map = new HashMap<>();
            Iterator<String> fieldNames = root.fieldNames();

            while(fieldNames.hasNext()) {
                String fieldName = fieldNames.next();
                JsonNode fieldValue = root.get(fieldName);
                map.put(fieldName, traverse(fieldValue));
            }
            return map;
        } else if(root.isArray()){
            // 当前node为json数组
            ArrayList<Object> list = new ArrayList<>();
            ArrayNode arrayNode = (ArrayNode) root;
            for(int i = 0; i < arrayNode.size(); i++) {
                JsonNode arrayElement = arrayNode.get(i);
                list.add(traverse(arrayElement));
            }
            return list;
        } else {
            // JsonNode root represents a single value field - do something with it.
            JsonToken jsonToken = root.asToken();
            switch (jsonToken) {
                case VALUE_STRING: return root.asText();
                case VALUE_NUMBER_INT: return root.asInt();
                case VALUE_NUMBER_FLOAT: return root.asDouble();
                case VALUE_TRUE: return root.asBoolean();
                case VALUE_FALSE: return root.asBoolean();
                default: return (String) null;
            }
        }
    }
}
